#pragma once
#include<iostream>
#include<memory>
#include<unordered_map>
#include"Multiplex.hpp"
#include"Connection.hpp"
static const int gnum = 64;
class Reactor
{
public:
    Reactor():_epoller(std::make_unique<Epoller>()),_isrunning(false)
    {
        
    };
    void AddConnection(int fd,uint32_t events,int type)
    {
        Connection* con =new Connection(fd);
        con->SetEvents(events);
        con->SetReactor(this);
        con->SetType(type);
        if(type ==ListenConnection)
            con->SetHandler(_OnConnection,nullptr,nullptr);
        else
            con->SetHandler(_OnRecver,_OnSender,_OnExcepter);
        if(!_epoller->AddEvent(fd,events))
            return;
        _Connections[fd] =con;
    }
    void SetOnConnect(handler_t OnConnection)
    {_OnConnection=OnConnection;}
    void SetNormalHandler(handler_t OnRecver,handler_t OnSender,handler_t OnExcepter)
    {
        _OnRecver=OnRecver;
        _OnSender=OnSender;
        _OnExcepter=OnExcepter;
    }
    void EnableConnectionReadWrite(int sockfd,bool readable,bool writeable)
    {
        if(!IsExistConnection(sockfd))
        return;
        uint32_t events =(readable?EPOLLIN:0)|(writeable?EPOLLOUT:0)|EPOLLET;
        _Connections[sockfd]->SetEvents(events);
        _epoller->ModEvent(sockfd,events);
    }
    bool IsExistConnection(int sockfd){
        return _Connections.count(sockfd);
    }

    void DelConnection(int sockfd)
    {
        if(!IsExistConnection(sockfd))
        return;
        //内核移除关心
        EnableConnectionReadWrite(sockfd,false,false);
        _epoller->DelEvent(sockfd);
        //关闭文件描述符
        _Connections[sockfd]->Close();
        //释放资源
        delete _Connections[sockfd];
        //Reactor移除管理
        _Connections.erase(sockfd);
    }

    void LoopOnce(int timeout)
    {
        int n =_epoller->Wait(revs,gnum,timeout);
        for(int i =0;i<n;i++)
        {
            int sockfd = revs[i].data.fd;
            int revents = revs[i].events;

            if((revents & EPOLLERR) || (revents & EPOLLHUP))
            {
            	revents|=(EPOLLIN|EPOLLOUT);//统一都交给读写IO处理
			}
            if(revents & EPOLLIN)
            {
                if(IsExistConnection(sockfd) && _Connections[sockfd]->_handler_recver)
                    _Connections[sockfd]->_handler_recver(_Connections[sockfd]);
            }

            if(revents&EPOLLOUT)
            {
                if(IsExistConnection(sockfd)&&_Connections[sockfd]->_handler_sender)
                    _Connections[sockfd]->_handler_sender(_Connections[sockfd]);
            }
        }
    }
    void PrintDebug()
    {
        std::string fdlist;
        for (auto &conn : _Connections)
        {
            fdlist += std::to_string(conn.second->Sockfd()) + " ";
        }
        LOG(DEBUG, "epoll管理的fd列表: %s\n", fdlist.c_str());
    }
    void Dispatcher()
    {
        int timeout =-1;
        _isrunning = true;
        while(true)
        {
            LoopOnce(timeout);
            PrintDebug();
        }
        _isrunning = false;
    }
private:

    std::unique_ptr<Multiplex> _epoller;
    unordered_map<int,Connection*> _Connections;
    bool _isrunning;
    struct epoll_event revs[gnum];

    //处理IO的方法集
    handler_t _OnConnection;
    handler_t _OnRecver;
    handler_t _OnSender;
    handler_t _OnExcepter;
};
